from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
from openai import OpenAI
import json
import logging
from dotenv import load_dotenv
import os
import sqlite3
import time

# 加载 .env 文件
load_dotenv()
deepseek_endpoint = os.getenv("DEEPSEEK_ENDPOINT")
deepseek_api_key = os.getenv("DEEPSEEK_API_KEY")
qw_endpoint = os.getenv("QW_ENDPOINT")
qw_api_key = os.getenv("QW_API_KEY")
qw_pic_model = os.getenv("QW_PIC_MODEL")
qw_plant_model = os.getenv("QW_PLANT_MODEL")
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)  # 启用调试日志



# 文字提问问题TODO解决方案
@app.route('/get_text_response', methods=['POST'])
def get_text_response():
    try:
        data = request.get_json()
        app.logger.debug(f"Received request data: {data}")  # 打印请求数据
        prompt = data.get('prompt')

        if not prompt:
            return jsonify({"error": "Missing 'prompt' in request"}), 400
        client = OpenAI(api_key=deepseek_api_key, base_url=deepseek_endpoint)
        # 调用 OpenAI API
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system",
                 "content": "你是个农业专业的教授,我会给你植物的病虫害类型,你要给我防治方案,分步骤来告诉我解决方案,回答要使用json模式来,name标识当前病虫害名称,solutions标识解决方案的列表，列表中元素结构如下：step标识这是第几步解决方案,method标识方法,description标识该方法的描述"},
                {"role": "user", "content": prompt},
            ],
            stream=False
        )

        # 检查响应结构
        if not response.choices or len(response.choices) == 0:
            return jsonify({"error": "Empty response from OpenAI"}), 500

        content = response.choices[0].message.content
        # app.logger.debug(f"Raw OpenAI response content: {content}")  # 打印原始内容

        # 尝试解析 JSON
        try:
            # content = content.replace("json","")
            cleaned_str = content.strip().strip('```json').strip('```').strip()
            parsed_content = json.loads(cleaned_str)
        except json.JSONDecodeError as e:
            app.logger.error(f"JSON解析失败: {str(e)}")
            return jsonify({"error": "Invalid JSON response from OpenAI", "raw_content": content}), 500

        # 写入记录
        try:
            _insert_record('text', prompt, parsed_content)
        except Exception:
            app.logger.exception("Failed to insert text record")

        return jsonify(parsed_content)

    except Exception as e:
        app.logger.exception("Unhandled exception occurred")  # 打印完整的错误堆栈
        return jsonify({"error": f"Internal server error: {str(e)}"}), 500


# 提交图片解答问题TODO解决方案 TODO 需要先把图片上传到某服务端获取图片链接
@app.route('/get_pic_response', methods=['POST'])
def get_pic_response():
    try:
        data = request.get_json()
        app.logger.debug(f"Received request data: {data}")  # 打印请求数据
        img_url = data.get('img_url')
        #
        if not img_url:
            return jsonify({"error": "Missing 'img_url' in request"}), 400
        client = OpenAI(api_key=qw_api_key,
                        base_url=qw_endpoint)
        # 调用 OpenAI API
        # qwen2.5-vl-72b-instruct
        response = client.chat.completions.create(
            model=qw_pic_model,
            messages=[
                {"role": "user", "content": [
                    {"type": "text",
                     "text": "你是个农业专业的教授,我会给你植物的图片，你帮我判断是什么病虫害,你要给我防治方案,分步骤来告诉我解决方案,回答要使用json模式来,name标识当前病虫害名称,solutions标识解决方案的列表，列表中元素结构如下：step标识这是第几步解决方案,method标识方法,description标识该方法的描述"},
                    {"type": "image_url",
                     "image_url": {"url": img_url}}
                ]},
            ],
            stream=False
        )
        print(response.model_dump_json())
        # 检查响应结构
        if not response.choices or len(response.choices) == 0:
            return jsonify({"error": "Empty response from OpenAI"}), 500

        content = response.choices[0].message.content
        app.logger.debug(f"Raw OpenAI response content: {content}")  # 打印原始内容

        # 尝试解析 JSON
        try:
            # content = content.replace("json","")
            cleaned_str = content.strip().strip('```json').strip('```').strip()
            parsed_content = json.loads(cleaned_str)
        except json.JSONDecodeError as e:
            app.logger.error(f"JSON解析失败: {str(e)}")
            return jsonify({"error": "Invalid JSON response from OpenAI", "raw_content": content}), 500

        # 写入记录
        try:
            _insert_record('pest', img_url, parsed_content)
        except Exception:
            app.logger.exception("Failed to insert pest record")

        return jsonify(parsed_content)

    except Exception as e:
        app.logger.exception("Unhandled exception occurred")  # 打印完整的错误堆栈
        return jsonify({"error": f"Internal server error: {str(e)}"}), 500

@app.route('/get_plant_response', methods=['POST'])
def get_plant_response():
    try:
        data = request.get_json()
        app.logger.debug(f"Received request data: {data}")  # 打印请求数据
        img_url = data.get('img_url')
        #
        if not img_url:
            return jsonify({"error": "Missing 'img_url' in request"}), 400
        client = OpenAI(api_key=qw_api_key,
                        base_url=qw_endpoint)
        # 调用 OpenAI API
        # qwen2.5-vl-72b-instruct
        response = client.chat.completions.create(
            model=qw_plant_model,
            messages=[
                {"role": "user", "content": [
                    {"type": "text",
                     "text": "你是个农业植物学专业的教授,我会给你植物的图片,你要给我这植物是什么科，什么属，什么种,回答要使用json模式来，其他注意内容不需要给我返回，只需要按照我的数据结构返回json即可。"
                             "name标识当前植物名称,details标识解决方案的字典，字典元素如下：family标识科，general标识属，species标识种,info标识这个植物的基本描述信息，area标识在中国的可能的生长区域，pharmacology标识药理特性,climate标识适合生长的气候条件（如亚热带、热带湿润气候）,soil_type 标识适宜的土壤类型（如黏土、壤土、沙壤土等),water_requirements 标识 对水分的需求（如需水量大、耐水淹等），growth_cycle 标识 生长周期（如一年生、多年生），history 标识该的起源与传播历史，cultural_significance 标识在文化中的重要性（如节日、习俗），cultivation_suggest标识种植栽培建议"},
                    {"type": "image_url",
                     "image_url": {"url": img_url}}
                ]},
            ],
            stream=False
        )
        print(response.model_dump_json())
        # 检查响应结构
        if not response.choices or len(response.choices) == 0:
            return jsonify({"error": "Empty response from OpenAI"}), 500

        content = response.choices[0].message.content
        app.logger.debug(f"Raw OpenAI response content: {content}")  # 打印原始内容

        # 尝试解析 JSON
        try:
            # content = content.replace("json","")
            cleaned_str = content.strip().strip('```json').strip('```').strip()
            parsed_content = json.loads(cleaned_str)
        except json.JSONDecodeError as e:
            app.logger.error(f"JSON解析失败: {str(e)}")
            return jsonify({"error": "Invalid JSON response from OpenAI", "raw_content": content}), 500

        # 写入记录
        try:
            _insert_record('plant', img_url, parsed_content)
        except Exception:
            app.logger.exception("Failed to insert plant record")

        return jsonify(parsed_content)

    except Exception as e:
        app.logger.exception("Unhandled exception occurred")  # 打印完整的错误堆栈
        return jsonify({"error": f"Internal server error: {str(e)}"}), 500

'''

你是个农业植物学专业的教授,我会给你植物的图片,你要给我这植物是什么科，什么属，什么种,回答要使用json模式来,name标识当前植物名称,details标识解决方案的字典，字典元素如下：family标识科，general标识属，species标识种,info标识这个植物的基本描述信息，area标识在中国的可能的生长区域，pharmacology标识药理特性
'''

# 允许的图片扩展名
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "webp"}

def _allowed_file(filename: str) -> bool:
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload_image', methods=['POST'])
def upload_image():
    try:
        if 'file' not in request.files:
            return jsonify({"error": "Missing file field 'file'"}), 400
        file = request.files['file']
        if file.filename == '':
            return jsonify({"error": "Empty filename"}), 400
        if not _allowed_file(file.filename):
            return jsonify({"error": "Unsupported file type"}), 400

        # 保存到 static/uploads 下
        upload_dir = os.path.join(os.path.dirname(__file__), 'static', 'uploads')
        os.makedirs(upload_dir, exist_ok=True)

        safe_name = secure_filename(file.filename)
        # 避免重名：在文件名前加上进程内唯一前缀
        unique_prefix = str(os.getpid()) + '_' + str(int(time.time()))
        filename = f"{unique_prefix}_{safe_name}"
        save_path = os.path.join(upload_dir, filename)
        file.save(save_path)

        # 构造可访问 URL（需后端可被公网访问，模型服务才能拉取）
        public_url = request.host_url.rstrip('/') + f"/static/uploads/{filename}"
        return jsonify({"url": public_url})
    except Exception as e:
        app.logger.exception("Upload failed")
        return jsonify({"error": f"Upload failed: {str(e)}"}), 500

# ===== 识别记录：SQLite 简易持久化 =====
_DB_PATH = os.path.join(os.path.dirname(__file__), 'records.db')

def _init_db():
    conn = sqlite3.connect(_DB_PATH)
    try:
        cur = conn.cursor()
        cur.execute(
            """
            CREATE TABLE IF NOT EXISTS records (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                type TEXT NOT NULL,
                input TEXT,
                output TEXT,
                created_at TEXT DEFAULT (datetime('now','localtime'))
            )
            """
        )
        conn.commit()
    finally:
        conn.close()

def _insert_record(record_type: str, input_value: str, output_obj: dict) -> None:
    conn = sqlite3.connect(_DB_PATH)
    try:
        cur = conn.cursor()
        cur.execute(
            "INSERT INTO records(type, input, output) VALUES (?, ?, ?)",
            (record_type, input_value or '', json.dumps(output_obj, ensure_ascii=False))
        )
        conn.commit()
    finally:
        conn.close()

def _row_to_dict(row):
    output_obj = json.loads(row[3]) if row[3] else None
    return {
        'id': row[0],
        'type': row[1],
        'input': row[2],
        'output': output_obj,
        'created_at': row[4],
    }

@app.route('/records', methods=['GET'])
def list_records():
    try:
        record_type = request.args.get('type')  # text | pest | plant | None
        limit = int(request.args.get('limit', '50'))
        limit = max(1, min(limit, 500))
        conn = sqlite3.connect(_DB_PATH)
        try:
            cur = conn.cursor()
            if record_type in ('text', 'pest', 'plant'):
                cur.execute(
                    "SELECT id, type, input, output, created_at FROM records WHERE type=? ORDER BY id DESC LIMIT ?",
                    (record_type, limit)
                )
            else:
                cur.execute(
                    "SELECT id, type, input, output, created_at FROM records ORDER BY id DESC LIMIT ?",
                    (limit,)
                )
            rows = cur.fetchall()
            return jsonify([_row_to_dict(r) for r in rows])
        finally:
            conn.close()
    except Exception as e:
        app.logger.exception('List records failed')
        return jsonify({"error": f"List failed: {str(e)}"}), 500

@app.route('/records/<int:record_id>', methods=['DELETE'])
def delete_record(record_id: int):
    try:
        conn = sqlite3.connect(_DB_PATH)
        try:
            cur = conn.cursor()
            cur.execute("DELETE FROM records WHERE id=?", (record_id,))
            conn.commit()
            return jsonify({"success": True, "id": record_id})
        finally:
            conn.close()
    except Exception as e:
        app.logger.exception('Delete record failed')
        return jsonify({"error": f"Delete failed: {str(e)}"}), 500

@app.route('/records', methods=['DELETE'])
def clear_records():
    try:
        conn = sqlite3.connect(_DB_PATH)
        try:
            cur = conn.cursor()
            cur.execute("DELETE FROM records")
            conn.commit()
            return jsonify({"success": True})
        finally:
            conn.close()
    except Exception as e:
        app.logger.exception('Clear records failed')
        return jsonify({"error": f"Clear failed: {str(e)}"}), 500

_init_db()

if __name__ == "__main__":
    app.run(debug=True)
